package com.ssy.lingxi.member.merchant.serviceimpl.web;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.ObjectUtil;
import com.ssy.lingxi.common.constant.CommonConstant;
import com.ssy.lingxi.common.constant.basic.EnableDisableStatus;
import com.ssy.lingxi.common.constant.basic.PlatformRuleTypeEnum;
import com.ssy.lingxi.common.constant.basic.PurchaseContractPayTypeEnum;
import com.ssy.lingxi.common.constant.member.BusinessCategoryInvoiceTypeEnum;
import com.ssy.lingxi.common.constant.member.MemberTypeEnum;
import com.ssy.lingxi.common.model.dto.UserLoginCacheDTO;
import com.ssy.lingxi.common.response.PageData;
import com.ssy.lingxi.common.response.ResponseCode;
import com.ssy.lingxi.common.response.Wrapper;
import com.ssy.lingxi.member.merchant.entity.MemberDO;
import com.ssy.lingxi.member.merchant.entity.MemberRelationDO;
import com.ssy.lingxi.member.merchant.entity.MemberUserDO;
import com.ssy.lingxi.member.merchant.entity.MemberVisitDO;
import com.ssy.lingxi.member.merchant.model.constant.*;
import com.ssy.lingxi.member.merchant.model.vo.basic.request.CommonIdRequest;
import com.ssy.lingxi.member.merchant.model.vo.basic.request.MemberVisitAddOrUpdateRequest;
import com.ssy.lingxi.member.merchant.model.vo.basic.request.MemberVisitListRequest;
import com.ssy.lingxi.member.merchant.model.vo.basic.response.MemberVisitListResponse;
import com.ssy.lingxi.member.merchant.model.vo.basic.response.MemberVisitTypeItemResponse;
import com.ssy.lingxi.member.merchant.model.vo.basic.response.VisitLevelResponse;
import com.ssy.lingxi.member.merchant.model.vo.basic.response.VisitTypeResponse;
import com.ssy.lingxi.member.merchant.model.vo.validate.response.*;
import com.ssy.lingxi.member.merchant.repository.MemberRepository;
import com.ssy.lingxi.member.merchant.repository.MemberUserRepository;
import com.ssy.lingxi.member.merchant.repository.MemberVisitRepository;
import com.ssy.lingxi.member.merchant.service.web.IMemberVisitService;
import com.ssy.lingxi.member.merchant.utils.NumberUtil;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.data.domain.*;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.http.HttpHeaders;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import javax.persistence.criteria.Join;
import javax.persistence.criteria.JoinType;
import javax.persistence.criteria.Predicate;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 会员拜访管理
 * @author wrc
 * @date 2020/6/19
 */
@Service
public class MemberVisitImpl implements IMemberVisitService {
    @Resource
    MemberVisitRepository memberVisitRepository;

    @Resource
    MemberUserRepository memberUserRepository;

    @Resource
    MemberRepository memberRepository;

    @Override
    public Wrapper<PageData<MemberVisitListResponse>> memberVisitList(MemberVisitListRequest request, UserLoginCacheDTO sysUser) {
        Pageable page = PageRequest.of(request.getCurrent() - 1, request.getPageSize(), Sort.by("updateTime").descending());
        Page<MemberVisitDO> pageList = memberVisitRepository.findAll((Specification<MemberVisitDO>) (root, query, cb) -> {
            List<Predicate> predicateList = new ArrayList<>();
            predicateList.add(cb.equal(root.get("createMemberId"), sysUser.getMemberId()));
            predicateList.add(cb.equal(root.get("createMemberRoleId"), sysUser.getMemberRoleId()));

            if (StringUtils.isNotEmpty(request.getMemberName())) {
                Join<MemberVisitDO, MemberDO> memberJoin = root.join("member", JoinType.LEFT);
                predicateList.add(cb.like(memberJoin.get("name").as(String.class), "%" + request.getMemberName().trim() + "%"));
            }

            if (StringUtils.isNotEmpty(request.getVisitTheme())) {
                predicateList.add(cb.like(root.get("visitTheme"), "%" + request.getVisitTheme() + "%"));
            }

            if (Objects.nonNull(request.getVisitType())) {
                predicateList.add(cb.equal(root.get("visitType"), request.getVisitType()));
            }

            if (Objects.nonNull(request.getVisitLevel())) {
                predicateList.add(cb.equal(root.get("visitLevel"), request.getVisitLevel()));
            }

            if (StringUtils.isNotEmpty(request.getVisitor())) {
                Join<MemberVisitDO, MemberUserDO> memberJoin = root.join("memberUser", JoinType.LEFT);
                predicateList.add(cb.like(memberJoin.get("name").as(String.class), "%" + request.getVisitor().trim() + "%"));
            }

            if (StringUtils.isNotEmpty(request.getPeer())) {
                predicateList.add(cb.like(root.get("peer"), "%" + request.getPeer() + "%"));
            }

            Predicate[] p = new Predicate[predicateList.size()];
            return query.where(predicateList.toArray(p)).getRestriction();
        }, page);

        List<MemberVisitListResponse> resultList = pageList.stream().map(memberVisitList -> {
            MemberVisitListResponse response = new MemberVisitListResponse();
            BeanUtils.copyProperties(memberVisitList, response);
            response.setMemberId(Optional.ofNullable(memberVisitList.getMember()).map(MemberDO::getId).orElse(null));
            response.setMemberName(Optional.ofNullable(memberVisitList.getMember()).map(MemberDO::getName).orElse(""));
            response.setVisitorId(Optional.ofNullable(memberVisitList.getMemberUser()).map(MemberUserDO::getId).orElse(null));
            response.setVisitor(Optional.ofNullable(memberVisitList.getMemberUser()).map(MemberUserDO::getName).orElse(""));
            response.setVisitTypeName(VisitTypeEnum.getNameByCode(NumberUtil.isNullOrZero(memberVisitList.getVisitType()) ? 0 : memberVisitList.getVisitType()));
            response.setVisitLevelName(VisitLevelEnum.getNameByCode(NumberUtil.isNullOrZero(memberVisitList.getVisitLevel()) ? 0 : memberVisitList.getVisitLevel()));
            return response;
        }).collect(Collectors.toList());
        return Wrapper.success(new PageData<>(pageList.getTotalElements(), resultList));
    }

    @Override
    public Wrapper<MemberVisitListResponse> memberVisitDetails(Long id) {
        MemberVisitDO memberVisitDO = memberVisitRepository.findById(id).orElse(null);
        if(ObjectUtil.isNull(memberVisitDO)){
            return Wrapper.fail(ResponseCode.RECORDS_DON_T_EXIST);
        }
        MemberVisitListResponse response = new MemberVisitListResponse();
        BeanUtils.copyProperties(memberVisitDO, response);
        response.setMemberId(Optional.ofNullable(memberVisitDO.getMember()).map(MemberDO::getId).orElse(null));
        response.setMemberName(Optional.ofNullable(memberVisitDO.getMember()).map(MemberDO::getName).orElse(""));
        response.setVisitorId(Optional.ofNullable(memberVisitDO.getMemberUser()).map(MemberUserDO::getId).orElse(null));
        response.setVisitor(Optional.ofNullable(memberVisitDO.getMemberUser()).map(MemberUserDO::getName).orElse(""));
        response.setVisitTypeName(VisitTypeEnum.getNameByCode(NumberUtil.isNullOrZero(memberVisitDO.getVisitType()) ? 0 : memberVisitDO.getVisitType()));
        response.setVisitLevelName(VisitLevelEnum.getNameByCode(NumberUtil.isNullOrZero(memberVisitDO.getVisitLevel()) ? 0 : memberVisitDO.getVisitLevel()));
        return Wrapper.success(response);
    }

    @Override
    public Wrapper<List<MemberVisitListResponse>> memberVisitAll(UserLoginCacheDTO sysUser) {
        Long memberId = sysUser.getMemberId();
        Long memberRoleId = sysUser.getMemberRoleId();
        List<MemberVisitDO> list = memberVisitRepository.findByCreateMemberIdAndCreateMemberRoleIdOrderByUpdateTimeDesc(memberId, memberRoleId);
        List<MemberVisitListResponse> resultList = list.stream().map(memberVisitList -> {
            MemberVisitListResponse response = new MemberVisitListResponse();
            BeanUtils.copyProperties(memberVisitList, response);
            response.setMemberId(Optional.ofNullable(memberVisitList.getMember()).map(MemberDO::getId).orElse(null));
            response.setMemberName(Optional.ofNullable(memberVisitList.getMember()).map(MemberDO::getName).orElse(""));
            response.setVisitorId(Optional.ofNullable(memberVisitList.getMemberUser()).map(MemberUserDO::getId).orElse(null));
            response.setVisitor(Optional.ofNullable(memberVisitList.getMemberUser()).map(MemberUserDO::getName).orElse(""));
            response.setVisitTypeName(Optional.ofNullable(memberVisitList.getMemberUser()).map(MemberUserDO::getName).orElse(""));
            return response;
        }).collect(Collectors.toList());
        return Wrapper.success(resultList);
    }

    @Override
    public Wrapper<Void> memberVisitAddOrUpdate(MemberVisitAddOrUpdateRequest request, UserLoginCacheDTO sysUser) {
        MemberDO memberDO = memberRepository.findById(request.getMemberId()).orElse(null);
        if (null == memberDO) {
            return Wrapper.fail("会员不存在");
        }
        MemberUserDO memberUserDO = memberUserRepository.findById(request.getVisitorId()).orElse(null);
        if (null == memberUserDO) {
            return Wrapper.fail("用户不存在");
        }
        MemberVisitDO MemberVisitDO = new MemberVisitDO();
        if(ObjectUtil.isNotNull(request.getId())){
            MemberVisitDO = memberVisitRepository.findById(request.getId()).orElse(null);
            if(ObjectUtil.isNull(MemberVisitDO)){
                return Wrapper.fail(ResponseCode.RECORDS_DON_T_EXIST);
            }
        }else{
            MemberVisitDO.setCreateMemberId(sysUser.getMemberId());
            MemberVisitDO.setCreateMemberRoleId(sysUser.getMemberRoleId());
            MemberVisitDO.setCreateTime(System.currentTimeMillis());
        }
        BeanUtils.copyProperties(request, MemberVisitDO);
        MemberVisitDO.setMember(memberRepository.findById(request.getMemberId()).orElse(null));
        MemberVisitDO.setMemberUser(memberUserRepository.findById(request.getVisitorId()).orElse(null));
        MemberVisitDO.setUpdateTime(System.currentTimeMillis());
        memberVisitRepository.saveAndFlush(MemberVisitDO);
        return Wrapper.success();
    }

    @Override
    public Wrapper<Void> memberVisitDelete(CommonIdRequest request) {
        MemberVisitDO memberVisitDO = memberVisitRepository.findById(request.getId()).orElse(null);
        if(ObjectUtil.isNull(memberVisitDO)){
            return Wrapper.fail(ResponseCode.RECORDS_DON_T_EXIST);
        }
        memberVisitRepository.deleteById(request.getId());
        return Wrapper.success();
    }

    @Override
    public Wrapper<MemberVisitTypeItemResponse> getMemberVisitOfVisitTypeItems(HttpHeaders headers) {
        MemberVisitTypeItemResponse itemVO = new MemberVisitTypeItemResponse();
        itemVO.setVisitTypes(Arrays.stream(VisitTypeEnum.values()).map(e -> new VisitTypeResponse(e.getCode(), e.getMsg())).sorted(Comparator.comparingInt(VisitTypeResponse::getVisitType)).collect(Collectors.toList()));
        itemVO.setVisitLevels(Arrays.stream(VisitLevelEnum.values()).map(e -> new VisitLevelResponse(e.getCode(), e.getMsg())).sorted(Comparator.comparingInt(VisitLevelResponse::getVisitLevel)).collect(Collectors.toList()));
        return Wrapper.success(itemVO);
    }
}
